//
//  MKImageBrowser.swift
//  MKPhotoDetailDemo
//
//  Created by 劢克科技 on 2019/3/26.
//  Copyright © 2019 劢克科技. All rights reserved.
//

import UIKit
import SnapKit

protocol MKImageBrowserDelegate {
    func handleBtnClick(index: Int)
}

class MKImageBrowser: UIViewController {
    
    //MARK: - Life Cycle
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        modalPresentationStyle = .overFullScreen
        transitioningDelegate = self
        
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gesture:)))
        view.addGestureRecognizer(longPress)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setUI()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        dismiss(animated: true)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        collectionView.scrollToItem(at: IndexPath(item: currentIndex, section: 0), at: UICollectionView.ScrollPosition.centeredHorizontally, animated: false)
        
        for cell in collectionView.visibleCells {
            if cell.isKind(of: MKVideoViewCell.self) {
                if (cell as! MKVideoViewCell).player == nil {
                    collectionView.reloadItems(at: [IndexPath(item: currentIndex, section: 0)])
                }
            }
        }
    }
    
    override func viewDidAppear(_ animated: Bool) {
        hideStatusBar()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        showStatusBar()
        
        for cell in videoCells {
            cell.deinitVideo()
        }
    }
    
    //MARK: - Setter
    
    var imageDatas = [MKImageData]()
    var currentIndex = 0 {
        didSet {
            indexLabel.text = "\(currentIndex + 1)/\(imageDatas.count)"
        }
    }
    
    //MARK: - Getter
    
    var delegate: MKImageBrowserDelegate?

    lazy var collectionView: UICollectionView = {
        let layout = MKImageViewLayout()
        let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
        collectionView.isPagingEnabled = true
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.showsVerticalScrollIndicator = false
        collectionView.showsHorizontalScrollIndicator = false
        // register
        collectionView.register(MKImageViewCell.self, forCellWithReuseIdentifier: "imageCell")
        collectionView.register(MKVideoViewCell.self, forCellWithReuseIdentifier: "videoCell")
        collectionView.backgroundColor = UIColor.black
        return collectionView
    }()
    
    let transitionManager = MKTransitionManager()
    
    lazy var indexLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor.white
        label.font = UIFont.systemFont(ofSize: 14)
        label.textAlignment = .center
        return label
    }()
    
    var videoCells = [MKVideoViewCell]()
    
    lazy var alertController: UIAlertController = {
        let controller = UIAlertController(title: "保存图片或视频到本地", message: "为了节省流量，请连接Wifi。", preferredStyle: UIAlertController.Style.actionSheet)
        let save = UIAlertAction(title: "保存", style: .default, handler: { (_) in
            self.saveSource()
        })
        let cancel = UIAlertAction(title: "取消", style: .cancel)
        controller.addAction(save)
        controller.addAction(cancel)
        return controller
    }()
}

//MARK: - Events

extension MKImageBrowser {
    
    // 隐藏状态栏
    fileprivate func hideStatusBar() {
        let window = UIApplication.shared.keyWindow
        window?.windowLevel = .alert
    }
    
    // 显示状态栏
    fileprivate func showStatusBar() {
        let window = UIApplication.shared.keyWindow
        window?.windowLevel = .normal
    }
    
    @objc fileprivate func handleLongPress(gesture: UILongPressGestureRecognizer) {
        if gesture.state == .began {
            present(alertController, animated: true, completion: nil)
        }
    }
    
    // 获取URL 保存图片或者视频到本地相册中
    fileprivate func saveSource() {
        let imageData = imageDatas[currentIndex]
        
        if imageData.isImage {
            saveImage(imageData: imageData)
        } else {
            saveVideo(videoData: imageData)
        }
    }
    
    fileprivate func saveVideo(videoData: MKImageData) {
        MKAlert(str: "开始下载")
        guard let videoUrl = videoData.videoUrl else {
            MKAlert(str: "保存失败")
            return
        }
        URLSession.shared.dataTask(with: videoUrl) { (data, response, err) in
            guard let data = data else {
                MKAlert(str: "保存失败")
                return
            }
            guard let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first else {
                MKAlert(str: "本地路径获取失败")
                return
            }
            let videoPath = (path as NSString).appendingPathComponent("saveVideo.mp4")
            let url = URL(fileURLWithPath: videoPath)
            (data as NSData).write(to: url, atomically: true)
            
            UISaveVideoAtPathToSavedPhotosAlbum(videoPath, nil, nil, nil)
            DispatchQueue.main.async {
                MKAlert(str: "保存成功")
            }
            }.resume()
    }
    
    fileprivate func saveImage(imageData: MKImageData) {
        guard let imageUrl = imageData.imageUrl else {
            MKAlert(str: "保存失败")
            return
        }
        MKAlert(str: "开始下载")
        URLSession.shared.dataTask(with: imageUrl) { (data, response, err) in
            if err == nil {
                DispatchQueue.main.async {
                    guard let data = data else {
                        MKAlert(str: "保存失败")
                        return
                    }
                    guard let image = UIImage(data: data) else {
                        MKAlert(str: "保存失败")
                        return
                    }
                    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
                    MKAlert(str: "下载成功")
                }
            } else {
                MKAlert(str: "保存失败")
            }
            }.resume()
    }
}

//MARK: - <TransitionDelegate>

extension MKImageBrowser: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        transitionManager.currentIndex = currentIndex
        transitionManager.imageDatas = imageDatas
        return transitionManager
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        transitionManager.currentIndex = currentIndex
        transitionManager.imageDatas = imageDatas
        return transitionManager
    }
}

//MARK: - <UICollectionViewDelegate, UICollectionViewDataSource>

extension MKImageBrowser: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imageDatas.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        if imageDatas.count > indexPath.item {
            if imageDatas[indexPath.item].videoUrl == nil {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! MKImageViewCell
                cell.currentIndex = indexPath.item
                cell.imageData = imageDatas[indexPath.item]
                cell.textInfo = imageDatas[indexPath.item].textInfo
                cell.delegate = self
                return cell
            } else {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for: indexPath) as! MKVideoViewCell
                if cell.url == nil {
                    cell.url = imageDatas[indexPath.item].videoUrl
                }
                if !videoCells.contains(cell) {
                    videoCells.append(cell)
                }
                cell.currentIndex = indexPath.item
                cell.delegate = self
                cell.imageData = imageDatas[indexPath.item]
                cell.textInfo = imageDatas[indexPath.item].textInfo
                return cell
            }
        }
        
        return UICollectionViewCell()
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        guard let cell = collectionView.visibleCells.first else { return }
        let index = Int((cell.frame.origin.x + 20) / collectionView.bounds.width)
        currentIndex = index
        
        let visibleCells = collectionView.visibleCells
        for cell in visibleCells {
            if cell.isKind(of: MKVideoViewCell.self) {
                (cell as! MKVideoViewCell).player?.play()
            }
            
            for videoCell in videoCells {
                if videoCell != cell {
                    videoCell.removePeriodicTimeObserver()
                    videoCell.deinitVideo()
                }
            }
        }
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        for cell in videoCells {
            cell.player?.pause()
        }
    }
}

//MARK: - <MKImageViewCellDelegate>

extension MKImageBrowser: MKImageViewCellDelegate {
    func btnClick(index: Int) {
        delegate?.handleBtnClick(index: index)
    }
    
    func cellDidTap() {
        dismiss(animated: true, completion: nil)
    }
    
    func shouldScroll(bool: Bool) {
        collectionView.isScrollEnabled = bool
    }
    
    func dismissNow() {
        dismiss(animated: false, completion: nil)
    }
    
    func clearBg() {
        showStatusBar()
        
        collectionView.backgroundColor = .clear
    }
    
    func fillBg() {
        hideStatusBar()
        
        collectionView.backgroundColor = .black
    }
}

//MARK: - UI

extension MKImageBrowser {
    fileprivate func setUI() {
        view.backgroundColor = UIColor.clear
        view.addSubview(collectionView)
        view.addSubview(indexLabel)
        indexLabel.snp.makeConstraints { (make) in
            make.left.equalTo(view.snp.left)
            if #available(iOS 11.0, *) {
                make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(10)
            } else {
                make.top.equalTo(view.snp.top).offset(20)
            }
            make.width.equalTo(UIScreen.main.bounds.width)
            make.height.equalTo(26)
        }
    }
}
